#include "BlockQueue.hpp"
#include <pthread.h>
#include <ctime>
#include <sys/types.h>
#include <unistd.h>
#include "Task.hpp"

class ThreadData
{
public:
    BlockQueue<Task> *bq;
    string name;
};

void *consumer(void *args)
{
    ThreadData *td = (ThreadData *)args;
    while (true)
    {
        // 1.消费数据
        Task t;
        td->bq->Pop(&t);
        // 2.处理数据
        t(); // 仿函数
        cout << "I am " << td->name << ", consumer data: " << t.PrintResult() << endl;
    }
    return nullptr;
}

void *productor(void *args)
{
   ThreadData *td = (ThreadData *)args;
    while (true)
    {
        // 1.有数据, 从具体场景中来, 从网络中拿数据
        int data1 = rand() % 10; //[0, 9]
        int data2 = rand() % 10; //[0, 9]
        char oper = opers[rand() % opers.size()];
        Task t(data1, data2, oper); // 构建任务
        // 2.进行生产
        td->bq->Push(t);
        // for debug
        cout << "I am " << td->name << ", productor data : " << t.PrintTask() << endl;
        sleep(1);
    }
    return nullptr;
}

int main()
{
    srand((uint16_t)time(nullptr) ^ getpid() ^ pthread_self()); // 形成更加随机的数
    BlockQueue<Task> *bq = new BlockQueue<Task>();
    pthread_t c[2], p[3];

    ThreadData *td1 = new ThreadData();
    td1->bq = bq;
    td1->name = "Thread-1";
    pthread_create(&c[0], nullptr, consumer, td1);

    ThreadData *td2 = new ThreadData();
    td2->bq = bq;
    td2->name = "Thread-2";
    pthread_create(&c[0], nullptr, consumer, td2);

    ThreadData *td3 = new ThreadData();
    td3->bq = bq;
    td3->name = "Thread-3";
    pthread_create(&p[0], nullptr, productor, td3);

    ThreadData *td4 = new ThreadData();
    td4->bq = bq;
    td4->name = "Thread-4";
    pthread_create(&p[0], nullptr, productor, td4);

    ThreadData *td5 = new ThreadData();
    td5->bq = bq;
    td5->name = "Thread-4";
    pthread_create(&p[0], nullptr, productor, td5);
    
    pthread_join(c[0], nullptr);
    pthread_join(c[1], nullptr);
    pthread_join(p[0], nullptr);
    pthread_join(p[0], nullptr);
    pthread_join(p[1], nullptr);
    pthread_join(p[2], nullptr);
    return 0;
}